#ifndef __NET_ADDRESS_HPP__
#define __NET_ADDRESS_HPP__
#include <string>
#include <sstream>
#include <stdio.h>
#include <boost/lexical_cast.hpp>
#ifdef _WIN32
#include <Winsock2.h>
#else 
#include <arpa/inet.h>
#endif 
namespace vpm 
{
	namespace utils 
	{
		class NetAddress
		{
		public:
			NetAddress()
			{
				m_host ="0.0.0.0";
				m_port = 0; 

			}

			explicit NetAddress(std::string host, unsigned short port)
			{
				m_host = host; 
				m_port = port;

			}

			explicit NetAddress(unsigned short port)
			{
				m_port = port; 
				m_host ="0.0.0.0";
			}

			std::string & host() 
			{
				return m_host; 
			}

			const std::string  host()  const 
			{
				return m_host; 
			}

			void host(const std::string& host)
			{
				m_host = host; 
			}

			void port(int p)
			{
				m_port =p ; 
			}


			unsigned short & port()
			{
				return m_port; 
			}

			const unsigned short port() const 
			{
				return m_port; 
			}

			void  ip( const unsigned long ip) 
			{
				m_host = NetAddress::htoa(ip);
			}

			static std::string ntoa(unsigned long ip)
			{
				char tmpBuf[64];
#ifdef _WIN32
				//sprintf_s(tmpBuf,sizeof(tmpBuf),"%u.%u.%u.%u", (ip>>24) &0xFF, (ip>>16)& 0xFF,(ip>>8)&0xFF, ip & 0xFF); 
				sprintf_s(tmpBuf,sizeof(tmpBuf),"%u.%u.%u.%u", ip & 0xFF,(ip>>8)&0xFF, (ip>>16)& 0xFF, (ip>>24) &0xFF);
#else
				sprintf(tmpBuf,"%u.%u.%u.%u", (unsigned int)ip & 0xFF,(unsigned int)(ip>>8)&0xFF, (unsigned int)(ip>>16)& 0xFF, (unsigned int)(ip>>24) &0xFF);
#endif
				return std::string(tmpBuf);
			}

			static std::string htoa( const unsigned long ip )
			{
				char tmpBuf[64];
#ifdef _WIN32
				//sprintf_s(tmpBuf,sizeof(tmpBuf),"%u.%u.%u.%u", (ip>>24) &0xFF, (ip>>16)& 0xFF,(ip>>8)&0xFF, ip & 0xFF);
				sprintf_s(tmpBuf,sizeof(tmpBuf),"%u.%u.%u.%u", (ip>>24) &0xFF, (ip>>16)& 0xFF,(ip>>8)&0xFF, ip & 0xFF);
#else 
				sprintf(tmpBuf,"%u.%u.%u.%u", (unsigned int)(ip>>24) &0xFF, (unsigned int)(ip>>16)& 0xFF,(unsigned int)(ip>>8)&0xFF, (unsigned int)ip & 0xFF);
#endif 
				return std::string(tmpBuf);
			}

			static unsigned long aton(const std::string & ipAddr)
			{
				unsigned long ip ; 
#ifdef _WIN32
				ip = inet_addr(ipAddr.c_str()); 
#else 
				inet_pton(AF_INET, ipAddr.c_str(), &ip);
#endif 
				return ip ; 
			}

			static unsigned long atoh(const std::string & ipAddr)
			{
				unsigned long ip = aton(ipAddr); 

				return ntohl(ip) ; 
			}


			unsigned long  ip() const 
			{

				return this->atoh(m_host);
				/*
				unsigned long ip; 
				#ifdef _WIN32
				ip = inet_addr(m_host.c_str()); 
				#else 
				inet_pton(AF_INET, m_host.c_str(), &ip);
				#endif 
				return ip;
				*/
			}
			/*
			bool operator == (const NetAddress &other) const 
			{
			return (this->m_host == other.m_host && m_port == other.m_port)?true:false; 
			}

			bool operator < (const NetAddress &other) const
			{
			if (this->ip() == other.ip())
			{
			return this->port() < other.port()? true:false; 
			}

			return this->ip()< other.ip() ? true:false; 			
			}
			*/

			bool is_any()  const 
			{
				return (m_host=="0.0.0.0");
			}

			std::string to_string() const 
			{
				std::stringstream strStream ; 
				strStream << m_host<<":" <<m_port; 
				return strStream.str(); 
			}

			static NetAddress  LOCAL_ADDRESS; 
			static NetAddress  ANY_ADDRESS; 

		private:
			std::string    m_host; // dot format string xxx.xxx.xxx.xxx
			unsigned short m_port; 

		}; 

		bool operator < (const NetAddress &self , const NetAddress &other) ;

		bool operator == (const NetAddress &self , const NetAddress &other) ;

	}
}

#endif //
